#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>
#include <limits.h>
#include <time.h>

#define INITIAL_NET 20 //!< Used to add offset to Netflix
#define INITIAL_YOU 50 //!< Used to add offset to Youtube
#define INITIAL_MEG 40 //!< Used to add offset to Megavideo
#define INITIAL_ZSH 100 //!< Used to add offset to Z Share
#define MAX_NUM_NETFLIX_USER_PACKETS 100   //!< Suppose to be: 8 gb/file x 1024 mb/gb x 1024 kb/mb x 1024 bytes/kb
#define MAX_NUM_YOUTUBE_USER_PACKETS 100   //!< Suppose to be: 8 gb/file x 1024 mb/gb x 1024 kb/mb x 1024 bytes/kb
#define MAX_NUM_ZSHARE_USER_PACKETS 100    //!< Suppose to be: 8 gb/file x 1024 mb/gb x 1024 kb/mb x 1024 bytes/kb
#define MAX_NUM_MEGAVIDEO_USER_PACKETS 100 //!< Suppose to be: 8 gb/file x 1024 mb/gb x 1024 kb/mb x 1024 bytes/kb
#define TOTAL_USERS 50

#define errorOccured(msg) printf("%s in file %s at line %d \n",(msg),__FILE__,__LINE__) //!< Prints error message stating line and file name.
#define PRINT_USER_SERVICE_INDEX 1
#define PRINT_SERVICE_LIST 1

#define NETFLIX_TIME_DEBUG 1
#define YOUTUBE_TIME_DEBUG 1
#define MEGAVIDEO_TIME_DEBUG 1

#define NUM_MEGAVIDEO 10
#define NUM_NETFLIX 20
#define NUM_YOUTUBE 30
#define NUM_ZSHARE 35

#define NUM_DSLAM 2
#define NUM_BRAS 2
#define NUM_USER 10

typedef struct timeval Time;

/** @struct Packet
 * Contains the fields required for each part of the simulation process
 */
struct packet {
    int userNumber; // Fill in while creating

    char source; //!< The service name. Can be N, M, Z, Y

    Time internetDispatchTime; //!< The begin time. Needed to calculate total time taken from internet to the user PC

    int brasNumber;
    Time brasBeginTime; //!< Required for Lindleys equation in BRAS
    Time brasDispatchTime; //!< Required for Lindleys equation in BRAS

    int routerNumber;
    Time routerBeginTime; //!< Required for Lindleys equation in router
    Time routerEndTime;

    int dslamNumber;
    Time dslamBeginTime;
    Time dslamDispatch; //!< Required to calculate total trip from internet to user PC

    Time timeReachedUser;

    int packetLost;
};

/** @fn mux
 * @brief merges streams of packets into one
 * @callergraph
 *
 * @return total number of packets in the final array
 */
int mux(struct packet*, struct packet*, struct packet*, struct packet*, struct packet*);

/** @fn demux
 * @brief seperates the incoming packet array into seperate arrays for each DSLAM
 * @callergraph
 *
 * @return nothing
 */
void demux(struct packet* incoming, int totalPackets);


